<?php

namespace App\Services;

use App\Services\Traits\Proxies;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Symfony\Component\DomCrawler\Crawler;

class BaiduSearchService
{
    use Proxies;
    protected $client;
//    private $proxies = []; // 代理IP列表
    private $currentProxyIndex = 0; // 当前使用的代理索引
    public function __construct()
    {
        $this->initProxies();
        $this->client = new Client([
            // 可以在这里设置代理等选项，以应对反爬或提高请求效率
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            ],
        ]);
        $this->proxies = $this->getProList();
        dd(json_decode($this->proxies,true));
//        $this->proxies = 123;
    }
    // 添加用于更新或重置代理IP列表的方法
    public function setProxies(array $proxies)
    {
        $this->proxies = $proxies;
        $this->currentProxyIndex = 0; // 重置当前使用的代理索引
    }
    public function search($query, $page = 1)
    {
        $url = "https://www.baidu.com/s?wd=site:{$query}&pn=" . (($page - 1) * 10);
        do {
            try {
                // 使用当前代理（如果有）
                if (!empty($this->proxies)) {
                    $this->applyProxy();
                }

                $response = $this->client->get($url);
                $body = (string) $response->getBody();

                // 检查是否遇到安全验证
                if ($this->isBaiduSecurityCheck($body)) {
                    $this->switchProxy(); // 遇到安全验证，切换代理
                    continue; // 切换后重新开始循环
                }

                $parsedResults = $this->parseSearchResults($body);
                $totalEstimate = $this->getTotalResultEstimate($body);
                return [
                    'results' => $parsedResults,
                    'total_estimate' => $totalEstimate,
                ];
            } catch (\Exception $e) {
                Log::error("Error fetching data from Baidu: " . $e->getMessage());
            }
        } while (!empty($this->proxies)); // 当还有代理可用时继续重试

        // 所有代理都尝试过或无代理可用时的处理
        return null; // 或者抛出异常，根据需求决定
    }

    // 应用当前代理到Guzzle客户端
    private function applyProxy()
    {
        if (isset($this->proxies[$this->currentProxyIndex])) {
            $proxy = $this->proxies[$this->currentProxyIndex];
            // 使用 withOptions 来动态设置代理
            $this->client = $this->client->withOptions([
                'proxy' => [
                    'http'  => $proxy,
                    'https' => $proxy,
                ],
            ]);
        }
    }

    // 切换到下一个代理
    private function switchProxy()
    {
        $this->currentProxyIndex++;
        if ($this->currentProxyIndex >= count($this->proxies)) {
            $this->currentProxyIndex = 0; // 重置回第一个代理，或根据策略处理代理耗尽的情况
        }
    }

    // 检查响应内容是否包含百度安全验证的标题
    private function isBaiduSecurityCheck($htmlContent)
    {
        $crawlerForTitle = new Crawler($htmlContent);
        $titleElement = $crawlerForTitle->filter('title')->first();
        return $titleElement && trim($titleElement->text()) === '百度安全验证';
    }
    public function parseSearchResults($htmlContent)
    {
        $crawler = new Crawler($htmlContent);
        // 假设百度搜索结果的标题和链接在特定的 CSS 选择器下，这里需要根据实际情况调整
        $results = [];
        $crawler->filter('.t a')->each(function ($node) use (&$results) {
            $title = trim($node->text());
            $link = $node->attr('href');
            $results[] = ['title' => $title, 'link' => $link];
        });
        return $results;
    }
    public function getTotalResultEstimate($htmlContent)
    {
        $crawler = new Crawler($htmlContent);
        // 注意这里的CSS选择器需要根据实际的百度搜索结果页面结构来调整
        // 示例选择器可能不准确，请根据实际页面HTML调整
        $estimateNode = $crawler->filter('#content_left')->first();
        if ($estimateNode) {
            $estimateText = trim($estimateNode->text());
            preg_match('/约\s*([0-9]{1,3}(?:,[0-9]{3})*|\\d+)个/', $estimateText, $matches);
            if (!empty($matches[1])) {
                $number = str_replace(',', '', $matches[1]);
                $number = intval($number); // 或者使用 floatval($number) 如果可能有小数
                return $number;
            }
        }
        return null;
    }
}
